package vista.objetos;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Point;
import java.util.LinkedList;
import java.util.List;

import javax.media.opengl.GL2;
import javax.media.opengl.awt.GLJPanel;

import controlador.ControladorDeTiposDeObjetos;
import eventos.EventoEtiquetaDeGraficable;

import vista.Tema;
import vista.geometria.Elipse;
import vista.paneles.hojaDibujo.HojaDeDibujo;
import vista.paneles.hojaDibujo.UtilHojaDeDibujo;

import logica.Atributo;
import logica.AtributoSimpleException;
import logica.persistencia.AtributoGraficableCopiaPersistente;
import logica.persistencia.GraficableConEtiquetaPersistente;

public class AtributoGraficableCompuesto extends AtributoGraficable {

	private List<AtributoGraficable> atributos;
	
	public void agregarAtributoGraficable(AtributoGraficable atrib) {
		this.atributos.add(atrib);
	}

	public AtributoGraficableCompuesto(Atributo atributo) throws AtributoTipoNoSoportadoException, AtributoSimpleException 
	{
		super(atributo);
		atributos = ControladorDeTiposDeObjetos.getInstancia().getAtributoGraficables(atributo.getAtributos());
	}
	
	private AtributoGraficableCompuesto(Atributo atributo, List<AtributoGraficable> atributos)
	{
		super(atributo);
		this.atributos = atributos;
	}
	
	public List<AtributoGraficable> getAtributosGraficables(){
		return this.atributos;
	}
	
	@Override
	public void dibujarse(Object areaDeDibujo) 
	{
		GL2 gl = (GL2)areaDeDibujo;
		Dimension tamano = this.getEtiqueta().getMinimumSize();
		float[] centroAtributoMundo = UtilHojaDeDibujo.getCoordMundo(gl, this.getPunto().x, this.getPunto().y);
		float[] dimensiones = UtilHojaDeDibujo.getDimensionMundo(gl, tamano.width/2, tamano.height/2);
		
		EstrategiaDeDistribucionDeAtributos.dibujarAtributos(gl, this.getAtributosGraficables(), this.getPunto());

		gl.glPushMatrix();
			gl.glTranslatef(centroAtributoMundo[0], centroAtributoMundo[1], 0.0f);
			Elipse.dibujarElipseRelleno(gl, dimensiones[0], dimensiones[1], 20.0f, Tema.getInstancia().getAtributoColor());
			gl.glColor3fv(Tema.getInstancia().getAtributoColor());
			Elipse.dibujarElipseContorno(gl, dimensiones[0], dimensiones[1], 20.0f);
		gl.glPopMatrix();		
	}
	
	@Override
	public AtributoGraficable copiarse() 
	{
		AtributoGraficableCompuesto atributoCopia = null;
		List<AtributoGraficable> atributosCopia = new LinkedList<>();
		
		atributoCopia = new AtributoGraficableCompuesto(getAtributo(), atributosCopia);
		atributoCopia.getPunto().setLocation(getPunto());
		atributoCopia.getEtiqueta().setLocation(this.getEtiqueta().getLocation());
		atributosCopia.addAll(this.copiarAtributos(atributoCopia.getPunto()));
		
		return atributoCopia;
	}
	
	private List<AtributoGraficable> copiarAtributos(Point nuevoCentro)
	{
		List<AtributoGraficable> atributosCopia = new LinkedList<>();
		AtributoGraficable atributoCopia;
		
		for (AtributoGraficable atributo: this.getAtributosGraficables()) 
		{
			atributoCopia = atributo.copiarse();
			atributoCopia.setPuntoCentroEntidad(nuevoCentro);
			atributosCopia.add(atributoCopia);
		}
		
		return atributosCopia;
	}
	public GraficableConEtiquetaPersistente getGraficableConEtiquetaPersistente() {
		return new AtributoGraficableCopiaPersistente(this);
	}
	
	@Override
	public void setUbicacionEtiqueta(int dx, int dy) 
	{		
		Point posicionAnterior = this.getEtiqueta().getLocation();

		this.setActualizarPosiciones(dx + posicionAnterior.x, dy +  posicionAnterior.y);
		this.setUbicacionEtiquetaDeAtributos(new Point(dx, dy));

	}

	private void setActualizarPosiciones(int x, int y)
	{
		this.getEtiqueta().setLocation(x, y);
		this.getPunto().setLocation(x + this.getEtiqueta().getWidth()/2, y + this.getEtiqueta().getHeight()/2);
	}

	private void setUbicacionEtiquetaDeAtributos(Point desplazamiento)
	{
		for (AtributoGraficable atributo: this.getAtributosGraficables()) 
            atributo.setUbicacionEtiqueta(desplazamiento.x, desplazamiento.y);
	}

	@Override
	public void setUbicacionCirculo()
	{
		this.getEtiqueta().setLocation(this.getPunto().x - this.getEtiqueta().getWidth()/2,
				this.getPunto().y - this.getEtiqueta().getHeight()/2);
	}
	
	@Override
	public void dragGraficable(Point desplazamiento)
	{
		super.setUbicacionEtiqueta(desplazamiento.x, desplazamiento.y);
		this.setUbicacionEtiquetaDeAtributos(desplazamiento);
	}
	
	@Override
	public void agregarEventoEtiqueta(HojaDeDibujo hoja)
	{
		super.agregarEventoEtiqueta(hoja);		
    	this.agregarEventoEtiquetaAtributo(hoja);
	}
	
	@Override
	protected EventoEtiquetaDeGraficable getEvento(HojaDeDibujo hoja) {
		return new EventoEtiquetaDeGraficable(hoja, this);
	}

	private void agregarEventoEtiquetaAtributo(HojaDeDibujo hoja) 
	{
    	for (AtributoGraficable atributo: this.getAtributosGraficables())
    		atributo.agregarEventoEtiqueta(hoja);
	}
	
	@Override
	public void agregarseAlCanvas(GLJPanel panel, Font fuente, Color color)
	{	  
		super.agregarseAlCanvas(panel, fuente, Tema.getInstancia().getFuenteColor());
		this.getEtiqueta().setLocation(this.getPunto().x - this.getEtiqueta().getWidth()/2, this.getPunto().y - this.getEtiqueta().getHeight()/2);
    	this.agregarAlCanvasAtributos(panel, fuente);
	}

	private void agregarAlCanvasAtributos(GLJPanel panel, Font fuente) 
	{
		for (AtributoGraficable atributo: this.getAtributosGraficables()) 
		{	
			atributo.setPuntoCentroEntidad(this.getPunto());
			atributo.setUbicacionCirculo();
            atributo.agregarseAlCanvas(panel, fuente, Tema.getInstancia().getFuenteColor());
		}
	}

	public void inicializarPosiciones()
	{
		this.setActualizarPosiciones(this.getPunto().x - this.getEtiqueta().getWidth()/2 , this.getPunto().y - this.getEtiqueta().getHeight()/2);
		EstrategiaDeDistribucionDeAtributos.calcularPosicionAtributoDefault(this.getAtributosGraficables(), this.getPunto());
	}
	
	@Override
	public void borrarseDeLaHoja() 
	{
		super.getContenedor().remove(this.getEtiqueta());
		borrarAtributos();
	}

	public void borrarAtributos() 
	{
		for (AtributoGraficable atributo: this.getAtributosGraficables()) 
			atributo.borrarseDeLaHoja();
	}

	@Override
	public void cambiarEscala(int nro)
	{
		super.cambiarEscala(nro);
		
		for (AtributoGraficable atributo : this.getAtributosGraficables())
			atributo.cambiarEscala(nro);
	}
	
	public boolean equals(Object atributo)
	{
		if (this.getClass().getName().compareToIgnoreCase(atributo.getClass().getName())!=0)
			return false;
		
		AtributoGraficableCompuesto atr = (AtributoGraficableCompuesto) atributo;
		
		//TODO falta ver lo del tipo
		return (atr.getAtributo().equals(this.getAtributo()));
		
	}
}
